#include "UserManager.hpp"
#include "Message.hpp"
#include "GetAvPacket.hpp"
#include "TcpConnection.hpp"
#include <iostream>
#include <memory>
using std::cout;
using std::endl;
using std::unique_ptr;
namespace wd{

using TcpConnectionptr = shared_ptr<TcpConnection>;

GetAvPacket::GetAvPacket(int camera_id,const string & url)
:_camera_id(camera_id)
,_url(url)
{

}
    
void GetAvPacket::process(){
    cout << "start GetAvPacket" << endl;

    AVFormatContext * pFormatCtx = nullptr; 
    AVDictionary * avdic = nullptr;

    pFormatCtx = avformat_alloc_context();
    if(!pFormatCtx){
        cout << "failed to allocate format context" << endl;
        return;
    }
    //设置字典参数
    av_dict_set(&avdic,"rtmp_transport","udp",0);
    av_dict_set(&avdic,"max_delay","100",0);
    
    //1.初始化网络
    avformat_network_init(); //初始化网络
    /* cout << "GetAvPacket:111" << endl; */
    //2.打开流
    if(avformat_open_input(&pFormatCtx,_url.data(),nullptr,&avdic)!=0){
        cout << "could not open rtsm stream"<<endl;
        av_dict_free(&avdic);
        return;
    }
    /* cout << "GetAvPacket:222" << endl; */
    cout << "open url success!" << endl;
    //3.找到流的信息
    if(avformat_find_stream_info(pFormatCtx,nullptr) < 0){
        cout << "could not find stream information" << endl;
        avformat_close_input(&pFormatCtx);
        return;
    }
    //打印媒体文件中流的信息
    av_dump_format(pFormatCtx,-1,_url.data(),0);

    /* cout << "GetAvPacket:333" << endl; */
    //4.找到最佳的流
    int videoStreamIdx = av_find_best_stream(pFormatCtx,AVMEDIA_TYPE_VIDEO,-1,-1,nullptr,0);
    if(videoStreamIdx < 0){
        cout << "could not find video stream" << endl;
        avformat_close_input(&pFormatCtx);
        return;
    }

    //打印 codecParameters 
    AVCodecParameters *codecpar =  pFormatCtx->streams[videoStreamIdx]->codecpar;
    cout << "codecpar->codec_type:" << codecpar->codec_type <<endl;
    cout << "codecpar->codec_id:" << codecpar->codec_id <<endl;
    cout << "codecpar->width:" << codecpar-> width <<endl;
    cout << "codecpar->height:" << codecpar->height <<endl;
    cout << "codecpar->format:" << codecpar->format <<endl;

    //5.读取数据包
    AVPacket * packet = av_packet_alloc();
    while(true){
        int ret = av_read_frame(pFormatCtx,packet);
        if(ret < 0){
                cout << "error reading frame:" << endl;
                break;
        }
        /* AVStream * stream = pFormatCtx->streams[packet->stream_index]; */

        if(packet->stream_index == videoStreamIdx){
            //将数据包发给客户端
            UserManger* user_manager = UserManger::getInstance();
            map<TcpConnectionptr, shared_ptr<User>> & user_info = user_manager->get_all_usersinfo();
            for(auto & u : user_info){
                shared_ptr<User> user = u.second;
                if(user->wanted_camera_id() == _camera_id){
                    //printf("\n Packet data (hex):--------- \n");
                    //for (int i = 0; i < (packet->size > 16 ? 16 : packet->size); i++) {
                    //    printf("%02x ", packet->data[i]);
                    //}
                    //printf("\n-------------------\n");

                    //发送数据包 
                    CameraPacketHeader header;
                    header.pts = packet->pts;
                    header.dts = packet->dts;
                    header.size = packet->size;
                    char* buf = new char[sizeof(header) + packet->size]();
                    memcpy(buf,&header,sizeof(header));
                    memcpy(buf+sizeof(header),packet->data,packet->size);

                    TLV2 tlv;
                    memset((void*)&tlv,0,sizeof(tlv));
                    
                    tlv.type = TASK_GET_CAMERA_DATA_OK;
                    tlv.length = sizeof(header) + packet->size; 
                    tlv.data = buf;
                    //cout << "\n-----------in GetAvPacket--------------\n" << endl
                    //    <<" packet->pts : " << packet->pts << endl
                    //    <<" packet->dts:" << packet->dts << endl
                    //    << "packet->size:" << packet->size << endl
                    //    << "send tlv.length:" << tlv.length << endl
                    //    << "sizeof(header):" << sizeof(header) << endl;

                    printf("tlv.data (hex):---------\n ");
                    for (int i = 0; i < (tlv.length > 16 ? 16 : tlv.length); i++) {
                        printf("%02x ", static_cast<unsigned char>(tlv.data[i + sizeof(header)]));  // 关键修复
                    }
                    printf("\n-------------------\n");

                    u.first->sendInLoop(tlv);
                    /* sleep(10); */
                }
            }
        }
        av_packet_unref(packet); //重置packet的状态
    }


}




}
